/*!
 * C2Rust 智能转换工具
 * 
 * 基于LLM的C到Rust代码转换系统
 */

use anyhow::Result;
use clap::{Arg, Command};
use std::path::PathBuf;
use tokio;

mod code_splitter;
mod config;
mod llm;
mod file_scanner;
mod llm_converter;
mod project_builder;
mod smart_fixer;

use config::Config;
use file_scanner::FileScanner;
use llm_converter::LlmConverter;
use project_builder::ProjectBuilder;

#[tokio::main]
async fn main() -> Result<()> {
    // 初始化日志
    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
        .target(env_logger::Target::Stdout)
        .init();

    // 解析命令行参数
    let matches = Command::new("c2rust")
        .version("0.1.0")
        .about("基于LLM的智能C到Rust转换工具")
        .arg(
            Arg::new("input")
                .help("输入的C项目路径或单个C文件")
                .required(true)
                .value_parser(clap::value_parser!(PathBuf))
                .index(1),
        )
        .arg(
            Arg::new("output")
                .help("输出的Rust项目路径")
                .short('o')
                .long("output")
                .value_parser(clap::value_parser!(PathBuf))
                .required(true),
        )
        .arg(
            Arg::new("config")
                .help("配置文件路径")
                .short('c')
                .long("config")
                .value_parser(clap::value_parser!(PathBuf)),
        )
        .arg(
            Arg::new("project-name")
                .help("生成的Rust项目名称")
                .short('n')
                .long("name")
                .value_parser(clap::value_parser!(String)),
        )
        .arg(
            Arg::new("verbose")
                .help("详细输出")
                .short('v')
                .long("verbose")
                .action(clap::ArgAction::SetTrue),
        )
        .get_matches();

    // 获取参数
    let input_path = matches.get_one::<PathBuf>("input").unwrap();
    let output_path = matches.get_one::<PathBuf>("output").unwrap();
    let config_path = matches.get_one::<PathBuf>("config");
    let project_name = matches
        .get_one::<String>("project-name")
        .map(|s| s.clone())
        .unwrap_or_else(|| {
            input_path
                .file_stem()
                .and_then(|s| s.to_str())
                .unwrap_or("c2rust_project")
                .to_string()
        });

    // 设置详细日志
    if matches.get_flag("verbose") {
        log::info!("启用详细输出模式");
    }

    log::info!("🚀 C2Rust 智能转换工具");
    log::info!("输入路径: {:?}", input_path);
    log::info!("输出路径: {:?}", output_path);
    log::info!("项目名称: {}", project_name);

    // 加载配置
    let config = if let Some(config_path) = config_path {
        Config::load(config_path)?
    } else {
        Config::default()
    };

    // 执行转换
    match convert_c_to_rust(input_path, output_path, &project_name, config).await {
        Ok(_) => {
            log::info!("✅ 转换完成！");
            log::info!("生成的Rust项目位于: {:?}", output_path);
            
            // 运行cargo check验证
            log::info!("🔍 验证生成的项目...");
            if let Err(e) = run_cargo_check(output_path).await {
                log::warn!("⚠️  项目验证发现问题: {}", e);
                log::info!("💡 这通常是正常的，因为复杂的C代码转换需要手动调整");
            } else {
                log::info!("✅ 项目验证通过！");
            }
        }
        Err(e) => {
            log::error!("❌ 转换失败: {}", e);
            std::process::exit(1);
        }
    }

    Ok(())
}

/// 核心转换逻辑
async fn convert_c_to_rust(
    input_path: &PathBuf,
    output_path: &PathBuf,
    project_name: &str,
    config: Config,
) -> Result<()> {
    
    // 第一步：扫描C文件
    log::info!("📂 第1步: 扫描C项目文件...");
    let scanner = FileScanner::new();
    let scan_result = if input_path.is_file() {
        // 单个文件
        let c_file = scanner.scan_single_file(input_path)?;
        file_scanner::ScanResult {
            source_files: vec![c_file],
            total_lines: 0,
        }
    } else {
        // 整个项目目录
        scanner.scan_project(input_path)?
    };
    
    log::info!("扫描完成: {} 个源文件, {} 行代码", 
              scan_result.source_files.len(), scan_result.total_lines);
    
    // 第二步：初始化LLM
    log::info!("🤖 第2步: 初始化LLM转换器...");
    let llm_assistant = if let Some(llm_config) = config.llm {
        llm::LlmAssistant::new(llm_config)?
    } else {
        return Err(anyhow::anyhow!("需要配置LLM设置"));
    };
    
    let mut converter = LlmConverter::new(llm_assistant);
    
    // 第三步：LLM转换
    log::info!("🔄 第3步: LLM智能转换C代码...");
    let mut rust_project = converter.convert_project(scan_result, project_name).await?;
    
    // 第四步：构建Cargo项目
    log::info!("📦 第4步: 构建Cargo项目...");
    let builder = ProjectBuilder::new();
    builder.build_project(&rust_project, output_path)?;
    
    // 第五步：自动修复编译错误
    log::info!("🔧 第5步: 自动修复编译错误...");
    match converter.auto_fix_compile_errors(&mut rust_project, output_path.as_ref()).await {
        Ok(()) => {
            log::info!("✅ 自动修复成功！项目编译通过");
        }
        Err(e) => {
            log::warn!("⚠️  自动修复部分成功或失败: {}", e);
            log::info!("💡 项目已生成，但可能需要手动调整部分代码");
        }
    }
    builder.validate_project(output_path)?;
    
    Ok(())
}

/// 运行cargo check验证项目
async fn run_cargo_check(project_path: &PathBuf) -> Result<()> {
    let output = tokio::process::Command::new("cargo")
        .arg("check")
        .current_dir(project_path)
        .output()
        .await?;
    
    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        return Err(anyhow::anyhow!("Cargo check 失败:\n{}", stderr));
    }
    
    Ok(())
}